package com.markhsiu.nio.proxy;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SocketChannel;

/**
 * http://ifeve.com/socket-channel/
 * @author Mark Hsiu
 *
 */
public class ProxyBuffer {

    private static enum BufferState {
    	FINISH_WRITE, FINISH_READ
    }

    private final static int BUFFER_SIZE = 8192;

    //大小需要控制，
    private final ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
    //默认必须是
    private BufferState state = BufferState.FINISH_WRITE;

    public boolean isFinishRead() {
        return state == BufferState.FINISH_READ;
    }

    public boolean isFinishWrite() {
        return state == BufferState.FINISH_WRITE;
    }

    public void read(SocketChannel channel) throws IOException {
    	//非阻塞模式下,read()方法在尚未读取到任何数据时可能就返回了
    	//该方法将数据从SocketChannel 读到Buffer中。read()方法返回的int值表示读了多少字节进Buffer里。
    	//如果返回的是-1，表示已经读到了流的末尾（连接关闭了）。
        int read = channel.read(buffer);
        if (read == -1) throw new ClosedChannelException();

        if (read > 0) {
            buffer.flip();
            state = BufferState.FINISH_READ;
        }
    }

    public void write(SocketChannel channel) throws IOException {
    	 
    	//非阻塞模式下，write()方法在尚未写出任何内容时可能就返回了
    	//注意SocketChannel.write()方法的调用是在一个while循环中的。Write()方法无法保证能写多少字节到SocketChannel。
    	//所以，我们重复调用write()直到Buffer没有要写的字节为止。
    	while(buffer.hasRemaining()) { 
    		channel.write(buffer);
    	}
       
        if (buffer.remaining() == 0) {
            buffer.clear();
            state = BufferState.FINISH_WRITE;
        }
    }

}

